﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Threading.Tasks;

namespace LazyTest
{
    public class Program
    {
        static void Main(string[] args)
        {
            #region lazy
            /////方式1   直接实例化
            //Console.WriteLine("直接实例化");
            //Lazy<Test> Way1 = new Lazy<Test>();
            //Console.WriteLine(Way1.IsValueCreated); 
            //Way1.Value.CWTest();
            //Console.WriteLine(Way1.IsValueCreated);
            //Console.ReadKey();

            /////方式3  反省封装
            //Console.WriteLine("泛型封装");
            //Lazy<Test> Way2 = LazyTool.ReturnClass<Test>();
            //Console.WriteLine(Way2.IsValueCreated);
            //Way2.Value.CWTest();
            //Console.WriteLine(Way1.IsValueCreated);
            //Console.ReadKey();

            /////方式3  通过委托创建
            //Console.WriteLine("通过委托创建");
            //Lazy<Test> Way3 = new Lazy<Test>(() => new Test());
            //Console.WriteLine(Way3.IsValueCreated);
            //Way3.Value.CWTest();
            //Console.WriteLine(Way1.IsValueCreated);
            //Console.ReadKey();

            /////方式3  封装，通过工厂创建
            //Console.WriteLine("封装，通过工厂创建");
            //MyLazy<Test> Way4 = new MyLazy<Test>(() => BigFactory.Build());
            //Way4.Value.CWTest();
            #endregion
            List<string> list = new List<string>();
            list.Add("123213");

            var mod = ReflectionCreate.CreateClass<Test>(list.ToArray());
            mod.CWTest();
            Console.ReadKey();
        }
    }

    public static class ReflectionCreate
    {
        public static T CreateClass<T>(Array parmaters)
        {
            var T_type = typeof(T);
            Console.WriteLine(T_type.Name);
            Console.WriteLine(T_type.FullName);
            Console.WriteLine(T_type.Assembly.FullName);
            Console.WriteLine(T_type.Namespace);
            Console.WriteLine(T_type.Assembly);
            return (T)Activator.CreateInstance(T_type,"1");
        }
    }

    public static class LazyTool
    {
        public static Lazy<T> ReturnClass<T>()
        {
            Lazy<T> dt = new Lazy<T>();
            return dt;
        }
    }

    public class Test
    {
        private string str;
        public Test(string stsr="") {
            this.str = stsr;
        }

        public void CWTest(string str = "")
        {
            Console.WriteLine("调用成功！");
            Console.WriteLine(str);
        }
    }

    /// <summary>
    /// 自定义工厂加载
    /// </summary>
    public class BigFactory
    {
        public static Test Build()
        {
            return new Test();
        }
    }

    /// <summary>
    /// 自定义封装懒加载
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class MyLazy<T>
    {
        private volatile object boxed; //volatile说明在多线程状况下，也可以修改该字段
        private Func<T> valueFactory; //委托，用来生产T对象实例

        static MyLazy() { }
        public MyLazy() { }

        public MyLazy(Func<T> valueFactory)
        {
            this.valueFactory = valueFactory;
        }

        public T Value
        {
            get
            {
                Boxed boxed = null;
                if (this.boxed != null)
                {
                    boxed = this.boxed as Boxed;
                    if (boxed != null)
                    {
                        return boxed.value;
                    }
                }
                return this.Init();
            }
        }

        //初始化对象实例
        private T Init()
        {
            Boxed boxed = null;
            if (this.boxed == null)
            {
                boxed = this.CreateValue();
                this.boxed = boxed;
            }
            return boxed.value;
        }

        //创建内部类实例
        private Boxed CreateValue()
        {
            //如果创建对象实例的委托valueFactory存在
            if (this.valueFactory != null)
            {
                //就通过委托生成对象实例
                return new Boxed(this.valueFactory());
            }
            else
            {
                //否则，通过反射生成对象实例
                return new Boxed((T)Activator.CreateInstance(typeof(T)));
            }
        }

        //内部嵌套类，通过构造函数对其字段赋值
        private class Boxed
        {
            internal T value;
            internal Boxed(T value)
            {
                this.value = value;
            }
        }
    }
}
